﻿/*
ChangeTracking (a library for POCO change tracking).

Copyright (C) 2014 Dmitry Merzagitovich Arslanov

This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at your option) any
later version.

This library is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*/

using System;
using System.Reflection;

namespace ChangeTracking
{
    /// <summary>
    /// Describes abstract relation between object instances.
    /// </summary>
    public abstract class Property : IEquatable<Property>
    {
        /// <summary>
        /// Property reflection information.
        /// </summary>
        public PropertyInfo Info { get; private set; }

        internal Property(PropertyInfo info)
        {
            Info = info;
        }

        /// <summary>
        /// Indicates whether the current object is equal to another object of
        /// the same type.
        /// </summary>
        /// <param name="other">An object to compare with this object.</param>
        /// <returns>
        /// True if the current object is equal to the other parameter;
        /// otherwise, false.
        /// </returns>
        public virtual bool Equals(Property other)
        {
            if (other == null) return false;
            return Info == other.Info;
        }

        /// <summary>
        /// Determines whether the specified object is equal to the current
        /// object.
        /// </summary>
        /// <param name="obj">
        /// The object to compare with the current object.
        /// </param>
        /// <returns>
        /// True if the specified object is equal to the current object;
        /// otherwise, false.
        /// </returns>
        public override bool Equals(object obj)
        {
            return Equals(obj as Property);
        }

        /// <summary>
        /// Serves as the default hash function.
        /// </summary>
        /// <returns>A hash code for the current object.</returns>
        public override int GetHashCode()
        {
            return Info.GetHashCode();
        }

        /// <summary>
        /// Returns a string that represents the current object.
        /// </summary>
        /// <returns>A string that represents the current object.</returns>
        public override string ToString()
        {
            return Info.Name;
        }

        /// <summary>
        /// Determines whether the specified property instances are considered
        /// equal.
        /// </summary>
        /// <param name="p1">The first property to compare.</param>
        /// <param name="p2">The second property to compare.</param>
        /// <returns>
        /// True if the properties are considered equal; otherwise, false.
        /// If both p1 and p2 are null, the method returns true.
        /// </returns>
        public static bool operator ==(Property p1,
                                       Property p2)
        {
            return Equals(p1, p2);
        }

        /// <summary>
        /// Determines whether the specified property instances are considered
        /// not equal.
        /// </summary>
        /// <param name="p1">The first property to compare.</param>
        /// <param name="p2">The second property to compare.</param>
        /// <returns>
        /// True if the properties are considered not equal; otherwise, false.
        /// If both p1 and p2 are null, the method returns false.
        /// </returns>
        public static bool operator !=(Property p1,
                                       Property p2)
        {
            return !Equals(p1, p2);
        }
    }
}
